`timescale 1ns / 1ps

///////////////////////////////////////////////////////////////////////
//																							//
//  Código extraido del libro "FPGA Prototyping By Verilog Examples",//
//  escrito por Pong P. Chu en su capítulo 13 "VGA Controller".		//
//																							//
///////////////////////////////////////////////////////////////////////
module sincronizador_vga(_clk_i, _rst_i,filas_o, columnas_o,hsync_o, vsync_o, video_o);
	
	//ENTRADAS
	input wire _clk_i, _rst_i;
	
	//SALIDAS
	output wire [9:0] filas_o, columnas_o;
	output wire hsync_o, vsync_o, video_o;
	 
	//PARAMETROS LOCALES
	//PARAMETROS DE SINCRONIZACION DE VGA 640x480
	localparam HD = 640;
	localparam HF = 48;
	localparam HB = 16;
	localparam HR = 96;
	localparam VD = 480;
	localparam VF = 10;
	localparam VB = 33;
	localparam VR = 2;
	
	//VARIABLES INTERNAS
	//CONTADOR mod-2
	reg mod2_reg;
	wire mod2_next;
	
	//CONTADORES DE SINCRONIZACION
	reg [9:0] h_count_reg, h_count_next;
	reg [9:0] v_count_reg, v_count_next;
	
	//BUFFERS DE SALIDA
	reg v_sync_reg, h_sync_reg;
	wire v_sync_next, h_sync_next;
	
	//SEÑAL DE STATUS
	wire h_end, v_end, pixel_tick;

	//GENERACION DE REGISTROS
	always @(posedge _clk_i, posedge _rst_i)
		if (_rst_i)
			begin
				mod2_reg <= 1'b0;
				v_count_reg <= 0;
				h_count_reg <= 0;
				v_sync_reg <= 1'b0;
				h_sync_reg <= 1'b0;
			end	
		else
			begin
				mod2_reg <= mod2_next;
				v_count_reg <= v_count_next;
				h_count_reg <= h_count_next;
				v_sync_reg <= v_sync_next;
				h_sync_reg <= h_sync_next;
			end
			
	//GENERACION DEL RELOJ DE 25MHz CON EL CIRCUITO mod-2
	assign mod2_next = ~mod2_reg;
	assign pixel_tick = mod2_reg;
	
	//FIN CONTADOR HORIZONTAL
	assign h_end = (h_count_reg==(HD+HF+HB+HR-1));
	
	//FIN CONTADOR VERTICAL
	assign v_end = (v_count_reg==(VD+VF+VB+VR-1));
	
	//LOGICA CONTADOR HORIZONTAL mod-800
	always @*
		if (pixel_tick) //25MHz
			if (h_end)
				h_count_next = 0;
			else
				h_count_next = h_count_reg + 1;
		else
			h_count_next = h_count_reg;
	
	//LOGICA CONTADOR VERTICAL mod-525
	always @*
		if (pixel_tick & h_end)
			if (v_end)
				v_count_next = 0;
			else 
				v_count_next = v_count_reg + 1;
		else
			v_count_next = v_count_reg;
			
	//SE HACEN PASAR LAS SEÑALES POR UN BUFFER PARA EVITAR GLITCHES
	//h_sync_nxt ASEGURADO ENTRE 656 y 751
	assign h_sync_next = (h_count_reg>=(HD+HB) && h_count_reg<=(HD+HB+HR-1));
	//v_sync_nxt ASEGURADO ENTRE 490 y 491
	assign v_sync_next = (v_count_reg>=(VD+VB) && v_count_reg<=(VD+VB+VR-1));
	
	//VIDEO ON/OFF
	assign video_o = (h_count_reg<HD) && (v_count_reg<VD);
	
	//SALIDAS
	assign hsync_o = h_sync_reg;
	assign vsync_o = v_sync_reg;
	assign filas_o = h_count_reg;
	assign columnas_o = v_count_reg;
	
endmodule
